package com.daigoudao.web.service.impl;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.daigoudao.util.AlipayCore;
import com.daigoudao.util.Constants;
import com.daigoudao.util.StringUtils;
import com.daigoudao.web.common.BusinessException;
import com.daigoudao.web.dao.IEvaluateDao;
import com.daigoudao.web.dao.IInviteDao;
import com.daigoudao.web.dao.ISimpleBuyDao;
import com.daigoudao.web.dao.ITransInfoDao;
import com.daigoudao.web.dao.IUserDao;
import com.daigoudao.web.dao.IWantBuyDao;
import com.daigoudao.web.model.BillModel;
import com.daigoudao.web.model.EvaluateModel;
import com.daigoudao.web.model.InviteModel;
import com.daigoudao.web.model.OrderDetailModel;
import com.daigoudao.web.model.PurchaseRecord;
import com.daigoudao.web.model.SimpleBuyModel;
import com.daigoudao.web.model.TransInfoModel;
import com.daigoudao.web.model.UserAttrModel;
import com.daigoudao.web.model.WantBuyModel;
import com.daigoudao.web.service.ITransInfoService;

public class TransInfoServiceImpl implements ITransInfoService {

	private static Logger alipayLogger = LoggerFactory.getLogger("aplipay");

	private ITransInfoDao transInfoDao;

	private IInviteDao inviteDao;

	private IWantBuyDao wantBuyDao;

	private IEvaluateDao evaluateDao;

	private ISimpleBuyDao simpleBuyDao;

	private IUserDao userDao;

	public void setSimpleBuyDao(ISimpleBuyDao simpleBuyDao) {
		this.simpleBuyDao = simpleBuyDao;
	}

	public void setEvaluateDao(IEvaluateDao evaluateDao) {
		this.evaluateDao = evaluateDao;
	}

	public void setTransInfoDao(ITransInfoDao transInfoDao) {
		this.transInfoDao = transInfoDao;
	}

	public void setInviteDao(IInviteDao inviteDao) {
		this.inviteDao = inviteDao;
	}

	public void setWantBuyDao(IWantBuyDao wantBuyDao) {
		this.wantBuyDao = wantBuyDao;

	}
	
	public void setUserDao(IUserDao userDao) {
		this.userDao = userDao;
	}

	/**
	 * 查询交易记录
	 * 
	 * @param transInfoModel
	 * @return
	 * @throws Exception
	 */
	public List<TransInfoModel> queryTransInfos(TransInfoModel transInfoModel)
			throws Exception {
		return transInfoDao.queryOrders(transInfoModel);
	}

	public void updateStatus(TransInfoModel transInfoModel) throws Exception {
		transInfoDao.updateStatus(transInfoModel);
		if (transInfoModel.getState() == 3) {
			TransInfoModel transInfo = transInfoDao.queryTran(transInfoModel
					.getTransId());
			if (transInfo.getSimpleId() != 0) {
				SimpleBuyModel simpleBuyModel = new SimpleBuyModel();
				simpleBuyModel.setSimpleId(transInfo.getSimpleId());
				simpleBuyModel.setStatus(3);
				simpleBuyDao.updateStatus(simpleBuyModel);
			} else if (transInfo.getWantId() != 0) {
				WantBuyModel wantBuyModel = new WantBuyModel();
				wantBuyModel.setWantId(transInfo.getWantId());
				wantBuyModel.setStatus(3);
				wantBuyDao.updateStatus(wantBuyModel);
			}
		}
	}

	public List<BillModel> queryBill(BillModel billModel) throws Exception {
		return transInfoDao.queryBill(billModel);
	}

	public List<BillModel> queryBillDetail(BillModel bill) throws Exception {
		return transInfoDao.queryBillDetail(bill);
	}

	@Override
	public int getBillCount(int brokerId) throws Exception {
		return transInfoDao.getBillCount(brokerId);
	}

	@Override
	public int getBillDetailCount(int brokerId) throws Exception {
		return transInfoDao.getBillDetailCount(brokerId);
	}

	@Override
	public void evaluate(TransInfoModel transInfoModel,
			EvaluateModel evaluateModel) throws Exception {
		transInfoDao.updateStatus(transInfoModel);
		evaluateDao.addEvaluate(evaluateModel);
	}

	public int getTransCount(TransInfoModel transInfoModel) throws Exception {
		return transInfoDao.getOrderCount(transInfoModel);
	}

	@Override
	public Map<Integer, Integer> groupTransInfoByUser(int userId)
			throws Exception {
		List<TransInfoModel> transInfoGroups = transInfoDao
				.groupTransInfoByUser(userId);
		Map<Integer, Integer> groupMap = new HashMap<Integer, Integer>();
		for (TransInfoModel transInfoModel : transInfoGroups) {
			groupMap.put(transInfoModel.getState(), transInfoModel.getNumber());
		}
		return groupMap;
	}

	@Override
	public Map<Integer, Integer> groupTransInfoByBroker(int userId)
			throws Exception {
		List<TransInfoModel> transInfoGroups = transInfoDao
				.groupTransInfoByBroker(userId);
		Map<Integer, Integer> groupMap = new HashMap<Integer, Integer>();
		for (TransInfoModel transInfoModel : transInfoGroups) {
			groupMap.put(transInfoModel.getState(), transInfoModel.getNumber());
		}
		return groupMap;
	}

	@Override
	public String getLastTransId() throws Exception {
		String lastOrderId = transInfoDao.getLastTransId();
		String curDate = StringUtils.formatDate(new Date(), "yyyyMMddHHmmss");
		if (lastOrderId == null) {
			lastOrderId = curDate + "000000";
		} else {
			String prefix = "";
			if (lastOrderId.length() > 14) {
				prefix = lastOrderId.substring(0, 14);
			}
			if (!prefix.equals(curDate)) {
				lastOrderId = curDate + "000000";
			}
		}
		return lastOrderId;
	}

	@Override
	public String addOrder(TransInfoModel order) throws Exception {
		order.setStartTime(new Date());
		calcFees(order);
		transInfoDao.addOrder(order);
		int orderId = order.getOrderId();
		for (int i = 0; i < order.getOrderDetails().size(); i++) {
			order.getOrderDetails().get(i).setOrderId(orderId);
		}
		// 写入详情
		transInfoDao.addOrderDetails(order.getOrderDetails());
		// 写入地址信息
		order.getAddress().setOrderId(order.getOrderId());
		transInfoDao.addAddress(order.getAddress());

		// 更新邀约表状态
		if (order.getInviteId() != 0) {
			InviteModel inviteModel = new InviteModel();
			inviteModel.setInviteId(order.getInviteId());
			inviteModel.setSelectMode(1);
			inviteDao.updateStatus(inviteModel);

			// 更改搭车求购信息的状态
			if (order.getSimpleId() != 0) {
				SimpleBuyModel simpleBuyModel = new SimpleBuyModel();
				simpleBuyModel.setSimpleId(order.getSimpleId());
				simpleBuyModel.setStatus(2);
				simpleBuyDao.updateStatus(simpleBuyModel);
			} else {
				// 更改求购信息的状态
				WantBuyModel wantBuyModel = new WantBuyModel();
				wantBuyModel.setWantId(order.getWantId());
				wantBuyModel.setStatus(2);
				wantBuyDao.updateStatus(wantBuyModel);
			}

		}
		return order.getTransId();
	}

	@Override
	public TransInfoModel queryTran(String tid) throws Exception {
		return transInfoDao.queryTran(tid);
	}

	@Override
	public TransInfoModel queryOrderDetail(TransInfoModel transInfoModel)
			throws Exception {
		return transInfoDao.queryOrderDetail(transInfoModel);
	}

	@Override
	public List<PurchaseRecord> queryPurchaseRecords(PurchaseRecord record)
			throws Exception {
		return transInfoDao.queryPurchaseRecords(record);
	}

	@Override
	public int getPurhcaseRecordCount(PurchaseRecord record) throws Exception {
		return transInfoDao.getPurhcaseRecordCount(record);
	}

	public TreeMap<String, String> getPayment(String tid) throws Exception {
		TreeMap<String, String> params = new TreeMap<String, String>();
		TransInfoModel transInfoModel = transInfoDao.queryTran(tid);
		if (transInfoModel != null && transInfoModel.getState() == 0) {
			params.put(Constants.OUT_TRADE_NO, transInfoModel.getTransId());
			params.put(Constants.SUBJECT, transInfoModel.getTransId());
			params.put(Constants.TOTAL_FEE, transInfoModel.getPayment() + "");
			AlipayCore.create_direct_pay_by_user(params);
			String sign = AlipayCore.buildMysign(params);
			params.put(Constants.SIGN, sign);
			params.put(Constants.SIGN_TYPE, Constants.SIGN_TYPE_VALUE);
		} else {
			params.put(Constants.ERR_MSG_KEY, "该交易不存在或已完成支付。");
		}
		return params;
	}

	@Override
	public void processAlipay(Map<String, String[]> alipayParams)
			throws Exception {
		TreeMap<String, String> params = new TreeMap<String, String>();
		for (Map.Entry<String, String[]> entry : alipayParams.entrySet()) {
			String[] values = entry.getValue();
			StringBuilder builder = new StringBuilder();
			for (int i = 0; i < values.length; i++) {
				if (i == values.length - 1) {
					builder.append(values[i]);
				} else {
					builder.append(values[i]).append(",");
				}
			}
			params.put(entry.getKey(), builder.toString());
		}
		alipayLogger.info("response params:\n{}", params);
		if (AlipayCore.verify(params)) {
			String tradeStatus = params.get("trade_status");
			if (Constants.TRADE_SUCCESS.equals(tradeStatus)
					|| Constants.TRADE_FINISHED.equals(tradeStatus)) {
				processOrder(params);
			}
		} else {
			throw new BusinessException("该消息不是支付宝发出的合法消息。");
		}
	}

	/**
	 * 处理交易信息
	 * 
	 * @param tid
	 */
	private synchronized void processOrder(TreeMap<String, String> params)
			throws Exception {
		String transId = params.get(Constants.OUT_TRADE_NO);
		TransInfoModel transInfo = transInfoDao.queryTran(transId);
		// 先判断该笔交易是否处理过
		if (transInfo != null && transInfo.getState() == 0) {
			TransInfoModel update = new TransInfoModel();
			update.setTransId(transId);
			update.setTradeNo(params.get("trade_no"));
			update.setState(1);
			update.setBuyerAlipayEmail(params.get("buyer_email"));
			update.setBuyerAlipayId(params.get("buyer_id"));
			Date payTime = null;
			if (params.containsKey("gmt_payment")) {
				payTime = StringUtils.parse(params.get("gmt_payment"),
						"yyyy-MM-dd HH:mm:ss");
			} else {
				payTime = new Date();
			}
			update.setPayTime(payTime);
			transInfoDao.updateStatus(update);
		}
	}

	/**
	 * 计算实际支付金额、平台服务费及其结算金额
	 * 
	 * @param order
	 */
	private void calcFees(TransInfoModel order) throws Exception {
		double payment = 0;
		double totalServiceFee = 0;
		for (OrderDetailModel detail : order.getOrderDetails()) {
			payment += detail.getSubTotal();
			totalServiceFee += detail.getServiceFee();
		}
		payment += order.getLogisticCharge();
		order.setPayment(payment);
		order.setServiceFee(totalServiceFee);

		// 计算平台服务费：platformFee = max(交易金额*0.02,代购服务费*平台服务费率, 5.0);
		double platformFee = payment * 0.02;
		UserAttrModel broker = userDao.getUserAttrByID(order.getBroker()
				.getUserid());
		if (broker != null) {
			float rate = broker.getRate();
			platformFee = Math.max(platformFee, order.getServiceFee() * rate
					/ 100);
		}
		platformFee = Math.max(platformFee, 5.0);
		order.setPlatformFee(platformFee);

		order.setSettlementAmount(payment - platformFee);
	}
}
